package com.example.byexample

import java.util.*

fun main() {

    // 数据类
    val user = User("Alex", 1)
    println(user)

    val secondUser = User("Alex", 1)
    val thirdUser = User("Max", 2)

    println("user == secondUser: ${user == secondUser}")
    println("user == thirdUser: ${user == thirdUser}")

    println(user.hashCode()) // 具有完全匹配属性的数据类实例具有相同的 hashCode。
    println(secondUser.hashCode())
    println(thirdUser.hashCode())

    println(user.copy())
    println(user === user.copy())
    println(user.copy(name = "Max"))
    println(user.copy(id = 3))

    println("name = ${user.component1()}") // 自动生成的 componentN 函数让您可以按照声明的顺序获取属性的值。
    println("id = ${user.component2()}")

    // 枚举类
    val state = State.RUNNING
    val message = when (state) {
        State.IDLE -> "It 's idle"
        State.RUNNING -> "It 's running"
        State.FINISHED -> "It 's finished"
        else -> "Unknown"
    }
    println("message")

    val red = Color.RED
    println(red)
    println(red.containsRed())
    println(Color.BLUE.containsRed())
    println(Color.YELLOW.containsRed())

    // Sealed Classes 密封类
    // 一旦你声明一个类是密封的，它就只能在声明了密封类的同一个包内被子类化。它不能在声明密封类的包之外进行子类化。
    println(greetMammal(Cat("Snowy")))

    // 类是蓝图，对象是类的实例。
    val d1 = LuckDispatcher()
    val d2 = LuckDispatcher()
    d1.getNumber()
    d2.getNumber()

    // 单例模式
    // 没有类，没有构造函数，只有一个惰性实例。为什么懒惰？因为在访问对象时会创建一次。否则，它甚至不会被创建。
    Singleton.debug

    // Object 关键字
    // 对象表达式
    rentPrice(10, 2, 1) // 调用函数。这是实际创建对象的时间。

    // 对象声明
    DoAuth.takeParams("foo", "qwerty") // 调用方法。这是实际创建对象的时间。

    // 伴随对象
    BigBen.getBongs(12) // 通过类名调用伴随对象方法。

    // 高阶函数
    // 高阶函数是将另一个函数作为参数或返回一个函数的函数。

}

class BigBen {
    companion object { // 定义同伴。它的名字可以省略。
        fun getBongs(nTimes: Int) { // 定义一个伴随对象方法。
            for (i in 1..nTimes) {
                print("BONG ")
            }
        }
    }
}

// 创建对象声明
object DoAuth {

    fun takeParams(username: String, password: String) { // 定义对象方法。
        println("input Auth parameters = $username:$password")
    }
}

// 租金
fun rentPrice(standardDays: Int, festivityDays: Int, specialDays: Int): Unit {
    val dayRates = object { // 创建一个对象，在计算结果值时使用。
        var standard: Int = 30 * standardDays
        var festivity: Int = 50 * festivityDays
        var special: Int = 100 * specialDays
    }

    val total = dayRates.standard + dayRates.festivity + dayRates.special // 访问对象的属性。

    print("Total price: $$total")
}

object Singleton {

    var debug: Boolean = false

}

// 定义类
class LuckDispatcher {
    fun getNumber() {
        var objRandom = Random()
        println(objRandom.nextInt(90))
    }
}

sealed class Mammal(val name: String) // 哺乳动物

class Cat(val catName: String) : Mammal(catName)

class Human(val humanName: String, val job: String) : Mammal(humanName)

fun greetMammal(mammal: Mammal): String {
    when (mammal) {
        is Human -> return "Hello ${mammal.name}; You're working as a ${mammal.job}"
        is Cat -> return "Hello ${mammal.name}"
    }
}

enum class Color(private val rgb: Int) {
    RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF), YELLOW(0xFFFF00);

    fun containsRed() = (this.rgb and 0xFF0000 != 0)
}

enum class State {
    IDLE, RUNNING, FINISHED
}

data class User(val name: String, val id: Int) {
    override fun equals(other: Any?): Boolean {
        return other is User && other.id == this.id
    }
}
